package com.crrc.dataparse.monitor.base.resource.xmlParse;

import com.crrc.dataparse.entity.*;
import com.crrc.dataparse.monitor.base.resource.IResource;
import com.crrc.dataparse.monitor.base.resource.MemoryResource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

public class XmlParser {
    private Document document;

    private Map<String, IResource> resourceMap;

    private String root = "protocol";

    private String PROTOCOL = "prot";

    private String PROTO_SOLU = "protSoln";

    private String TEMPLATE = "template";

    private String TEMPLATE_SOLU = "tmpSoln";

    private String PARAMETER = "para";

    private String PARAMETER_SOLU = "pSoln";


    private String RSC_TEMPPARA = "templatePara";

    private String RSC_TEMPPARA_OID = "temppara_oid";

    private String RSC_SOURCE2PROTOCL = "source2Protocol";

    private String RSC_PROTOCL = "protocol";

    private String RSC_TEMPLATE = "template";

    private String RSC_SUBTEMPLATE = "subTemplate";

    private String RSC_TEMPLATE_OID = "template_oid";


    public XmlParser(String filename) {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder db = dbf.newDocumentBuilder();
            File file = new File(filename);
            this.document = db.parse(file);
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Map<String, IResource> getResource() {
        if (this.resourceMap == null)
            parse();
        return this.resourceMap;
    }

    private void parse() {
        this.resourceMap = new HashMap<>();
        parseParameter();
        parseTemplate();
        parseProtocol();
    }

    private void parseProtocol() {
        MemoryResource memoryResource1 = new MemoryResource();
        MemoryResource memoryResource2 = new MemoryResource();
        Map<String, ProTreatClass> map = new HashMap<>();
        NodeList solu = this.document.getElementsByTagName(this.PROTO_SOLU);
        for (int i = 0; i < solu.getLength(); i++) {
            ProTreatClass ptc = new ProTreatClass();
            NodeList attr = solu.item(i).getChildNodes();
            for (int k = 0; k < attr.getLength(); k++) {
                String name = attr.item(k).getNodeName();
                String value = attr.item(k).getTextContent();
                switch (name) {
                    case "plt_oid":
                        ptc.setOid(value);
                        break;
                    case "plt_treatname":
                        ptc.setTreatName(value);
                        break;
//                    case "plt_classname":
//                        ptc.setClassName(value);
//                        break;
                }
            }
            map.put(ptc.getOid(), ptc);
        }

        NodeList protList = this.document.getElementsByTagName(this.PROTOCOL);
        for (int j = 0; j < protList.getLength(); j++) {
            Protocol protocol = new Protocol();
            protocol.setLinePara("75C55AABDFE9FB43B2BE8ED78259834F");
            protocol.setCarPara("CE82507C380AAC40B6728C550ADDD555");
            protocol.setTerminalPara("9D7233108FFA1C4DBA12795A5C7BA068");
            NodeList attr = protList.item(j).getChildNodes();
            int k;
            for (k = 0; k < attr.getLength(); k++) {
                NodeList l;
                int m;
                String name = attr.item(k).getNodeName();
                String value = attr.item(k).getTextContent();
                switch (name) {
                    case "plt_oid":
                        protocol.setOid(value);
                        break;
                    case "plt_protname":
                        protocol.setProtocalName(value.trim());
                        break;
                    case "plt_packetsource":
                        protocol.setPacketSource(value);
                        break;
                    case "plt_treatclass":
                        if (value == null || value.trim().length() == 0)
                            break;
                        protocol.setTemplateRecogClass(map.get(value));
                        break;
                    case "plt_parsepara":
                        protocol.setTempRegParameter(value);
                        break;
                    case "plt_verifyclass":
                        protocol.setVerifyClass(value);
                        break;
                    case "tempOidList":
                        protocol.setPro2TempList(new ArrayList());
                        l = attr.item(k).getChildNodes();
                        for (m = 0; m < l.getLength(); m++) {
                            String type = l.item(m).getNodeName();
                            if (type != "#text") {
                                Node temp = l.item(m);
                                String tempoid = temp.getTextContent();
                                Pro2Temp t2tp = new Pro2Temp();
                                t2tp.setProtocol(protocol);
                                t2tp.setTemplate((Template)((IResource)this.resourceMap.get(this.RSC_TEMPLATE_OID)).getResourceItem(tempoid));
                                protocol.getPro2TempList().add(t2tp);
                            }
                        }
                        break;
                }
            }
            for (k = 0; k < attr.getLength(); k++) {
                String name = attr.item(k).getNodeName();
                if (name == "paraOidList") {
                    NodeList paras = attr.item(k).getChildNodes();
                    protocol.setParaList(new ArrayList());
                    for (int m = 0; m < paras.getLength(); m++) {
                        String type = paras.item(m).getNodeName();
                        if (type != "#text") {
                            String paraOid = paras.item(m).getTextContent();
                            Element element = (Element)paras.item(m);
                            Pro2TemPara p2tp = new Pro2TemPara(protocol.getOid(), paraOid, Integer.valueOf(Integer.parseInt(element.getAttribute("order"))), Integer.valueOf(Integer.parseInt(element.getAttribute("offset"))));
                            protocol.getParaList().add(p2tp);
                            protocol.getParaList().sort(new Comparator<Pro2TemPara>() {
                                @Override
                                public int compare(Pro2TemPara o1, Pro2TemPara o2) {
                                    return o1.getOrder().intValue() - o2.getOrder().intValue();
                                }
                            });
                        }
                    }
                }
            }
            memoryResource1.addResourceItem(protocol.getOid(), protocol);
            memoryResource2.addResourceItem(protocol.getPacketSource(), protocol);
        }
        this.resourceMap.put(this.RSC_PROTOCL, memoryResource1);
        this.resourceMap.put(this.RSC_SOURCE2PROTOCL, memoryResource2);
    }

    private void parseTemplate() {
        MemoryResource memoryResource1 = new MemoryResource();
        MemoryResource memoryResource2 = new MemoryResource();
        MemoryResource memoryResource3 = new MemoryResource();
        NodeList soluList = this.document.getElementsByTagName(this.TEMPLATE_SOLU);
        Map<String, TempTreClass> map = new HashMap<>();
        for (int i = 0; i < soluList.getLength(); i++) {
            TempTreClass ttc = new TempTreClass();
            NodeList attr = soluList.item(i).getChildNodes();
            for (int k = 0; k < attr.getLength(); k++) {
                String name = attr.item(k).getNodeName();
                String value = attr.item(k).getTextContent();
                switch (name) {
                    case "plt_oid":
                        ttc.setOid(value);
                        break;
                    case "plt_treatname":
                        ttc.setTreatName(value);
                        break;
//                    case "plt_classname":
//                        ttc.setClassName(value);
//                        break;
                }
            }
            map.put(ttc.getOid(), ttc);
        }
        NodeList tempList = this.document.getElementsByTagName(this.TEMPLATE);
        for (int j = 0; j < tempList.getLength(); j++) {
            Template template = new Template();
            NodeList attr = tempList.item(j).getChildNodes();
            for (int k = 0; k < attr.getLength(); k++) {
                NodeList paras;
                int m;
                String name = attr.item(k).getNodeName();
                String value = attr.item(k).getTextContent();
                switch (name) {
                    case "plt_oid":
                        template.setOid(value);
                        break;
                    case "plt_tempid":
                        template.setTemplateID(value);
                        break;
                    case "plt_tempname":
                        template.setTemplateName(value);
                        break;
                case "plt_parseparameter":
                    template.setParseParameter(value);
                    break;
                case "plt_fixedlength":
                    if (value == null || value.trim().length() == 0)
                        break;
                    template.setFixedLength(Integer.valueOf(Integer.parseInt(value)));
                    break;
                case "plt_versionlist":
                    template.setVersionList(value);
                    break;
                case "plt_isstorerawdata":
                    if (value == null || value.trim().equals("false")) {
                        template.setStoreRawData(false);
                        break;
                    }
                    template.setStoreRawData(true);
                    break;
                case "plt_treatclass":
                    if (value == null)
                        break;
                    template.setParseClassName(map.get(value));
                    break;
                case "paraOidList":
                    paras = attr.item(k).getChildNodes();
                    template.setTem2TemParaList(new ArrayList());
                    for (m = 0; m < paras.getLength(); m++) {
                        String type = paras.item(m).getNodeName();
                        if (type != "#text") {
                            String paraOid = paras.item(m).getTextContent();
                            Element element = (Element)paras.item(m);
                            Tem2TemPara t2tp = new Tem2TemPara();
                            t2tp.setOffset(element.getAttribute("offset"));
                            t2tp.setTpOrder(Integer.valueOf(Integer.parseInt(element.getAttribute("order"))));
                            t2tp.setTemplate(template);
                            t2tp.setTemplatePara((TemplatePara)((IResource)this.resourceMap.get(this.RSC_TEMPPARA_OID)).getResourceMapItem(paraOid));
                            template.getTem2TemParaList().add(t2tp);
                            template.getTem2TemParaList().sort(new Comparator<Tem2TemPara>() {
                                @Override
                                public int compare(Tem2TemPara o1, Tem2TemPara o2) {
                                    return o1.getTpOrder().intValue() - o2.getTpOrder().intValue();
                                }
                            });
                        }
                    }
                    break;
            }
        }
//        try {
//            if (template.getTemplateType().booleanValue() == true) {
//                memoryResource2.addResourceItem(template.getTemplateID(), template);
//            } else {
//                memoryResource1.addResourceItem(template.getTemplateID(), template);
//            }
//        } catch (Exception e) {
//            System.out.print(template);
//            e.printStackTrace();
//        }
        memoryResource3.addResourceItem(template.getOid(), template);
    }
    this.resourceMap.put(this.RSC_TEMPLATE, memoryResource1);
    this.resourceMap.put(this.RSC_SUBTEMPLATE, memoryResource2);
    this.resourceMap.put(this.RSC_TEMPLATE_OID, memoryResource3);
}

    private void parseParameter() {
        MemoryResource memoryResource1 = new MemoryResource();
        MemoryResource memoryResource2 = new MemoryResource();
        Map<String, ParaTreatClass> soluMap = new HashMap<>();
        NodeList solu = this.document.getElementsByTagName(this.PARAMETER_SOLU);
        for (int i = 0; i < solu.getLength(); i++) {
            ParaTreatClass paramTr = new ParaTreatClass();
            NodeList list = solu.item(i).getChildNodes();
            for (int k = 0; k < list.getLength(); k++) {
                String name = list.item(k).getNodeName();
                String value = list.item(k).getTextContent();
                switch (name) {
                    case "plt_oid":
                        paramTr.setOid(value);
                        break;
                    case "plt_treatname":
                        paramTr.setTreatName(value);
                        break;
                    case "plt_classname":
                        paramTr.setClassName(value);
                        break;
                }
                soluMap.put(paramTr.getOid(), paramTr);
            }
        }
        NodeList paramList = this.document.getElementsByTagName(this.PARAMETER);
        for (int j = 0; j < paramList.getLength(); j++) {
            NodeList attrs = paramList.item(j).getChildNodes();
            TemplatePara param = new TemplatePara();
            for (int k = 0; k < attrs.getLength(); k++) {
                TPara2Treat t2p;
                Node n = attrs.item(k);
                String name = n.getNodeName();
                String value = n.getTextContent();
                switch (name) {
                    case "plt_oid":
                        param.setOid(value);
                        break;
                    case "plt_paraid":
                        param.setParameterID(value);
                        break;
                    case "plt_paraname":
                        param.setParameterName(value);
                        break;
                    case "plt_paralength":
                        if (value == null || value.trim().length() == 0)
                            break;
                        param.setLength(Integer.valueOf(Integer.parseInt(value)));
                        break;
                    case "plt_resolution":
                        if (value == null || value.trim().length() == 0)
                            break;
                        param.setResolution(Float.valueOf(Float.parseFloat(value)));
                        break;
                    case "plt_offset2":
                        if (value == null || value.trim().length() == 0)
                            break;
                        param.setOffset(Float.valueOf(Float.parseFloat(value)));
                        break;
                    case "plt_datatype":
                        if (value == null || value.trim().length() == 0)
                            break;
                        switch (value.trim()) {
                            case "Int":
                                param.setInfoType(Integer.valueOf(1));
                                break;
                            case "Long":
                                param.setInfoType(Integer.valueOf(2));
                                break;
                            case "Float":
                                param.setInfoType(Integer.valueOf(3));
                                break;
                            case "Double":
                                param.setInfoType(Integer.valueOf(4));
                                break;
                            case "Boolean":
                                param.setInfoType(Integer.valueOf(5));
                                break;
                            case "Geo":
                                param.setInfoType(Integer.valueOf(6));
                                break;
                            case "String":
                                param.setInfoType(Integer.valueOf(7));
                                break;
                        }
                        break;
                    case "plt_extension":
                        param.setExtension(value);
                        break;
                    case "plt_bigendian":
                        if (value == null || !value.trim().equals("true")) {
                            param.setBigEndianData(false);
                        } else {
                            param.setBigEndianData(true);
                        }
                    case "solnOid":
                        if (value == null || value.trim().length() == 0)
                            break;
                        t2p = new TPara2Treat();
                        t2p.setTemplatePara(param);
                        t2p.setParaTreatClass(soluMap.get(value));
                        param.settPara2TreatList(new ArrayList());
                        param.gettPara2TreatList().add(t2p);
                        break;
                    case "plt_paratype":
                        if (value == null || value.trim().length() == 0)
                            break;
                        switch (value.trim()) {
                            case "基础信息参数":case "基础信息变量":
                                param.setParameterType(Integer.valueOf(1));
                                break;
                            case "工况参数":case "工况变量":
                                param.setParameterType(Integer.valueOf(2));
                                break;
                            case "子模板参数":case "子模板变量":
                                param.setParameterType(Integer.valueOf(3));
                                break;
                            case "预留参数":case "预留变量":
                                param.setParameterType(Integer.valueOf(4));
                                break;
                            case "虚拟参数":case "虚拟变量":
                                param.setParameterType(Integer.valueOf(5));
                                break;
                            case "统计参数":case "统计变量":
                                param.setParameterType(Integer.valueOf(6));
                                break;
                            case "基础信息参数-线路":case "基础信息变量-线路":
                                param.setParameterType(Integer.valueOf(7));
                                break;
                            case "基础信息参数-设备":case "基础信息变量-设备":
                                param.setParameterType(Integer.valueOf(8));
                                break;
                            case "基础信息参数-终端":case "基础信息变量-终端":
                                param.setParameterType(Integer.valueOf(9));
                                break;
                            case "基础信息参数-时间":case "基础信息变量-时间":
                                param.setParameterType(Integer.valueOf(10));
                                break;
                            case "基础信息参数-车型":case "基础信息变量-车型":
                                param.setParameterType(Integer.valueOf(11));
                                break;
                        }
                        break;
                    case "plt_paraNum" :
                        if (!value.equals("")) {
                        param.setParaNum(Integer.valueOf(value));
                        break;
                    }
                        else value = "1";
                        param.setParaNum(Integer.valueOf(value));
                }
            }
            memoryResource2.addResourceMapItem(param.getOid(), param);
            memoryResource1.addResourceMapItem(param.getParameterID(), param);
        }
        this.resourceMap.put(this.RSC_TEMPPARA, memoryResource1);
        this.resourceMap.put(this.RSC_TEMPPARA_OID, memoryResource2);
    }
}
